import { catchErr, checkNet, checkResult, checkToken } from "./check"
import util from "./util"

type params = {
  url: string,
  method?: 'POST' | 'GET' | 'DELETE' | 'PUT',
  data?: any,
  header?: any,
  noToken?: boolean,
}

class Request {
  pending: ((p: any) => void)[] = [] // 请求中的接口
  isRefresh: boolean = false // 正在刷新token

  constructor() {
    // 监听网络状态
    const CALLBACK = (res: any) => {
      if (!res.isConnected) {
        util.totast('网络连接已断开 ~')
      }
    }
    uni.offNetworkStatusChange(CALLBACK)
    uni.onNetworkStatusChange(CALLBACK)
  }

  request(params: params) {
    const { isExpire, isNeedRefresh, tokenObj } = checkToken()

    if (!params.noToken) {
      if (isNeedRefresh) {
        if (!this.isRefresh) {
          this.isRefresh = true
          this.refreshToken(tokenObj.refresh_token)
        }
        return new Promise((resolve, reject) => {
          this.pending.push((isSuccess: boolean, err?: any) => {
            if (isSuccess) {
              resolve(this.request(params))
            } else {
              reject(err)
            }
          })
        })
      }
    }
    return new Promise((resolve, reject) => {
      const token = uni.getStorageSync('token')
      const token_obj = token ? JSON.parse(token) : {}
      let url = util.domain + params.url
      // #ifdef H5
      url = params.url
      // #endif
      uni.request({
        url,
        method: params.method,
        data: params.data,
        header: params.header || {
          "Content-Type": "application/json",
          Authorization: !params.noToken && `${token_obj.token_type} ${token_obj.access_token}`
        },
        timeout: 5000,
        dataType: 'json',
        responseType: 'text',
        success: res => {
          resolve(res)
        },
        fail: err => {
          reject(err)
        },
      })
    })
  }

  query(params: params) {
    let p = {
      ...params,
      data: params.data?.query ? JSON.stringify(params.data) : params.data
    }
    return checkNet().then(() =>
      this.request(p).then(checkResult).catch(catchErr))
      .catch(catchErr)
  }

  /**
   * 刷新token过程中，请求排队
   * @param is_success 
   * @param res 
   */
  handler(is_success: boolean, res?: any) {
    this.isRefresh = false
    this.pending.forEach((callback: any) => {
      callback(is_success, res)
    })
    this.pending = []
  }

  /**
   * 刷新token
   * @param refreshToken 
   */
  async refreshToken(refreshToken: string) {
    try {
      const { data, statusCode }: any = await this.request({
        url: '/sjzsj-rights-api/sjzsj/refresh-token',
        method: 'GET',
        data: {
          refreshToken
        },
      })
      if (statusCode == 200) {
        uni.setStorageSync('start_date_token', new Date().getTime())
        uni.setStorageSync('token', JSON.stringify(data))
        this.handler(true)
      } else {
        this.handler(false, data)
      }
    } catch (err) {
      this.handler(false, err)
    }
  }
}

export default new Request;